#include <iostream>
#include <opencv2/core.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>

cv::Mat laplace_of_gaussian(const cv::Mat& mat, int ksize, double sigma) {
    cv::Mat gaussian, log;
    cv::GaussianBlur(mat, gaussian, cv::Size(ksize, ksize), sigma, sigma, cv::BORDER_REFLECT101);
    cv::Laplacian(gaussian, log, CV_8UC1, 1, 1.0, 0.0, cv::BORDER_REFLECT101);
    return log;
}

cv::Mat difference_of_gaussian(const cv::Mat& mat, int ksize, double sigma1, double sigma2) {
    cv::Mat g1, g2;
    cv::GaussianBlur(mat, g1, cv::Size(ksize, ksize), sigma1, sigma1, cv::BORDER_REFLECT101);
    cv::GaussianBlur(mat, g2, cv::Size(ksize, ksize), sigma2, sigma2, cv::BORDER_REFLECT101);
    cv::Mat g = g1 - g2;
    return g;
}

int main(int argc, char **argv) {
    cv::Mat mat = cv::imread("/home/xlll/Downloads/opencv/samples/data/lena.jpg", cv::IMREAD_GRAYSCALE);
    if (mat.empty()) {
        std::cout << "failed to read image!" << std::endl;
        return EXIT_FAILURE;
    }
    
    double k = 1.6;
    double sigma2 = 1, sigma1 = k*sigma2;
    double sigma1_2 = sigma1*sigma1;
    double sigma2_2 = sigma2*sigma2;
    double sigma = sigma1_2*sigma2_2*cv::log(sigma1_2/sigma2_2)/(sigma1_2 - sigma2_2);
    int ksize = 11;
    cv::Mat LoG = laplace_of_gaussian(mat, ksize, sigma);
    cv::Mat DoG = difference_of_gaussian(mat, ksize, sigma1, sigma2);
    
    cv::imshow("mat", mat);
    cv::imshow("LoG", LoG);
    cv::imshow("DoG", DoG);
    cv::waitKey(0);
    return EXIT_SUCCESS;
}
